package droid.mapViewer.utils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Iterator;
import java.util.List;

public class PointsFloatBuffer {
	private static final float z = 0;
	
	private FloatBuffer points;
	private int count;
	private FloatBuffer rectArea;	//Прямоугольная область вокруг полигона. Нужна для Setencil-буфера
	
	private PointsFloatBuffer(FloatBuffer points, FloatBuffer rectArea, int count) { //О да! Закрытый конструктор! я так долго этого ждал! ;)
		this.points=points;
		this.count=count;
		this.rectArea=rectArea;
	}
	
	public FloatBuffer getBuffer() {
		return points;
	}
	
	public int count() {
		return count;
	}
	
	public FloatBuffer getRectBuffer() {
		return rectArea;
	}
	/**
	 * Если параметр <code>center</code> не-<code>null</code>, то в полученном буфере первой точкой будет <code>center</code>.
	 * В противном случае дополнительная точка добавлена не будет.  
	 */
	public static PointsFloatBuffer convertToFloatBuffer(List<Point> points, Point center) {
		ByteBuffer bb;
		ByteBuffer rectbb = ByteBuffer.allocateDirect(12 * 6); //Прямоугольник, он и есть прямоугольник - 4 вершины, 
		//1 - центр и последняя вершина повторяет первую
		if (center != null) 
			bb = ByteBuffer.allocateDirect(12 * (points.size()+1)); //Еще центр добавим
		else
			bb = ByteBuffer.allocateDirect(12 * (points.size()));
		bb.order(ByteOrder.nativeOrder());
		rectbb.order(ByteOrder.nativeOrder());
		FloatBuffer buf = bb.asFloatBuffer();
		
		FloatBuffer rectbuf = rectbb.asFloatBuffer();
		float minX = getMin(points, Point.X_ID);
		float minY = getMin(points, Point.Y_ID);
		float maxX = getMax(points, Point.X_ID);
		float maxY = getMax(points, Point.Y_ID);
		rectbuf.put((minX+maxX)/2f);
		rectbuf.put((minY+maxY)/2f);
		rectbuf.put(z);
		rectbuf.put(minX);
		rectbuf.put(minY);
		rectbuf.put(z);
		rectbuf.put(minX);
		rectbuf.put(maxY);
		rectbuf.put(z);
		rectbuf.put(maxX);
		rectbuf.put(maxY);
		rectbuf.put(z);
		rectbuf.put(maxX);
		rectbuf.put(minY);
		rectbuf.put(z);
		rectbuf.put(minX);
		rectbuf.put(minY);
		rectbuf.put(z);
		rectbuf.position(0);
		
		if (center != null) {
			buf.put(center.getx());
			buf.put(center.gety());
			buf.put(z);
			
		}
		for (int i=0; i<points.size(); i++) {
			buf.put(points.get(i).getx());
			buf.put(points.get(i).gety());
			buf.put(z);
		}
		buf.position(0);
		
/*		FloatBuffer bbox;
		ByteBuffer bb = ByteBuffer.allocateDirect(12 * 7);
		bb.order(ByteOrder.nativeOrder());
		bbox = bb.asFloatBuffer(); 
		bbox.put(0.068609f);
		bbox.put(0.375464f);
		bbox.put(0);
		bbox.put(-0.431125f);
		bbox.put(1.496487f);
		bbox.put(0);
		bbox.put(-1.160465f);
		bbox.put(0.105339f);
		bbox.put(0);
		bbox.put(0.406267f);
		bbox.put(-0.745558f);
		bbox.put(0);
		bbox.put(1.297683f);
		bbox.put(0.821173f);
		bbox.put(0);
		bbox.put(-0.282553f);
		bbox.put(1.455969f);
		bbox.put(0);
		bbox.put(-0.431125f);
		bbox.put(1.496487f);
		bbox.put(0);
		bbox.position(0);*/
		if (center != null)
			return new PointsFloatBuffer(buf, rectbuf, points.size()+1);
		else
			return new PointsFloatBuffer(buf, rectbuf, points.size());
	}
	
	/**
	 * @param id - идентификатор координаты x или y
	 */
	private static float getMin(List<Point> points, int id) {
		float min = Float.MAX_VALUE;
		float tmp;
		Iterator<Point> i = points.iterator();
		while (i.hasNext()) {
			tmp =i.next().getCoord(id); 
			if (min>tmp)
				min=tmp;
		}
		return min;
	}
	
	private static float getMax(List<Point> points, int id) {
		float max = Float.MIN_VALUE;
		float tmp;
		Iterator<Point> i = points.iterator();
		while (i.hasNext()) {
			tmp =i.next().getCoord(id); 
			if (max<tmp)
				max=tmp;
		}
		return max;
	}
}
